package com.mrzhou.rabbit.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author qiang.zhou
 */
@Configuration
public class ThreadPoolConfiguration {

    private final String INSERT_USER_EXECUTOR = "INSERT_USER_EXECUTOR";

    @Bean(INSERT_USER_EXECUTOR)
    public Executor threadPoolExecutable() {
        int cpu = Runtime.getRuntime().availableProcessors();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(cpu, 2 * cpu, 60, TimeUnit.SECONDS, new LinkedBlockingQueue());
        executor.setThreadFactory(new InsertThreadFactory("insert-database-thread-"));
        // 启动当前的线程池的监视线程
        Thread thread = new Thread(new InsertThreadPoolMonitor(executor, INSERT_USER_EXECUTOR));
        thread.setName("insert-thread-pool-monitor");
        thread.start();
        return executor;
    }

     private class InsertThreadFactory implements ThreadFactory {

         private final AtomicInteger threadNumber = new AtomicInteger(1);
         private final String namePrefix;

         InsertThreadFactory(String namePrefix) {
             this.namePrefix = namePrefix+"-";
         }

         @Override
         public Thread newThread(Runnable r) {
             Thread t = new Thread( r, namePrefix + threadNumber.getAndIncrement());
             if (t.isDaemon()) {
                 t.setDaemon(true);
             }
             if (t.getPriority() != Thread.NORM_PRIORITY) {
                 t.setPriority(Thread.NORM_PRIORITY);
             }
             return t;
         }
     }

     private static class InsertThreadPoolMonitor implements Runnable {

        private static final Logger logger = LoggerFactory.getLogger(InsertThreadPoolMonitor.class);

        private final ThreadPoolExecutor executor; // 需要监视的线程池

        private final String executorName; // 需要监视的线程池名称

         private InsertThreadPoolMonitor(ThreadPoolExecutor executor, String executorName) {
             this.executor = executor;
             this.executorName = executorName;
         }

         @Override
         public void run() {
             while(true) {
                 int queueSize = executor.getQueue().size();
                 if (queueSize == 0) {
                     try {
                         Thread.sleep(30000);  // 当前线程池中没有需要处理的任务时, 休眠30s
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
                 } else {
                     logger.info("[{}]线程池状态：待处理任务： {},  活动线程数： {},  执行完成的线程数： {},  总线程数： {},  当前线程数： {},  初始线程数量：{},  最大线程数量：{}",
                             executorName,
                             executor.getQueue().size(),
                             executor.getActiveCount(),
                             executor.getCompletedTaskCount(),
                             executor.getTaskCount(),
                             executor.getPoolSize(),
                             executor.getCorePoolSize(),
                             executor.getMaximumPoolSize());
                     try {
                         Thread.sleep(10000);  // 每隔10秒查询一次线程池状态
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
                 }
             }

         }

     }

}
